JavaScript Nested functions and clousers

    In the last JavaScript tutorial, we learned about JavaScript function Scope and how the global and local Scope and variables work in JavaScript. If you do not know what are global and local scopes please check that tutorial first, because in this tutorial we will be frequently referencing both terms.

    JavaScript Nested Functions

    In JavaScript, we can define a function inside a function, and it is known as a nested function. As we already know that when a function is defined it creates a local scope and all the variables defined in that local scope are known as local variables, that can be accessed only inside the function. The same concept goes for nested functions, when we define a new function inside the function the newly created inner function becomes a local function and only be accessed by the outer function. Example

    <script>
        function outerFunc()
        {
            function innerFunc()
            {
                document.write("Inner Function called");
            }
            innerFunc();    // call innerFunc
        }
    
        outerFunc(); //call outerFunc
    
        innerFunc();  // error 
    
    </script>

    Output

    Behind the Code In the above example, we defined nested innerFunc() function inside the outerFunc() , and called the innerFunc() inside only, using innerFunc() statement. Because of top to bottom interpreter code execution approach, when we called the outerFunc() it executed the outerFucn() statement as well as innerFunc() because we have called the innerFunc() inside the outerFunc() . But when we try to call the innerFunc() outside the outerFunc() code block, it throws an error, innerFunc is not defined because if anything is defined inside the function, becomes the part of function's local scope and only be accessed inside the function. So is there any other way of accessing the inner nested function from outside the outer function? Yes, we can return the inner function itself and assign it to a variable and with that, we can use the inner function anywhere throughout the program.

    Example

    <script>
        function outerFunc()
        {
            function innerFunc()
            {
                document.write("Inner Function called");
            }
    
           return innerFunc; //retun the function itslf
        }
    
        let innerFunc = outerFunc(); //retrun  innerFunc
    
        innerFunc() // call innerFunc outside the outerFunc 
    </script>

    Output

    Inner Function called

    Behind the code In the above example instead of calling the innerFucn() inside the outerFunc() we are returning the innerFunc() . Be careful when you return the inner function. In the above example you can see that we are only returning the inner Function name innerFunc , we have applied not parentheses with it. And when we call the outer function outerFunc() it returns the inner function, and we have assigned that inner function to a new variable called innerFunc (you can use any other variable name). Now the newly created innerFunc variable has become the function, and like a normal funciton, we can execute it using parentheses after its name.

    Closures in JavaScript

    From the function scope tutorial, we already know that when a function is called and done executing all its local scope variables get destroyed automatically. But Clousers redefine this nature of JavaScript function up to some extent. A nested function or inner function can access the outer function local scope variables like an outer function can access global variables. And if an inner function is using some of the out function local scope variables the inner function will keep remembering the value of outer funciton local variables ever after the Outer function is done executing and all of its other local variables are destroyed. And this keeps remembering the data of outer function variables by the inner functions is known as closures. We have already seen a glimpse of JavaScirpt closures in working in the above example where are able to access the inner function even after the Outer funciton is done executing. Now let's see how can an inner function use the closure features to remember the local variables of the outer function. Example

    <script>
        function outerFunc()
        {
    
            o_name ="Outer Function"  //local variable
    
            function innerFunc()
            {   i_name ="Inner Function"
                document.write("The Value of o_name is: "+o_name); // access outer function o_name
                document.write("<br>"); // new line
                document.write("The value of i_name is: "+i_name);
            }
    
           return innerFunc; //retun the function itslf
        }
    
        let innerFunc = outerFunc(); //retrun  innerFunc
    
        innerFunc() // call innerFunc outside the outerFunc 
    
    </script>
    Output
    The Value of o_name is: Outer Function
    The value of i_name is: Inner Function
    Behind the code In the above example, we are accessing the value of o_name inside the function innerFunc() , even after the outerFunc() is done executing in the statement let innerFunc = outerFunc(); . But it's all thanks to closures feature of JavaScript the innerFunc() keep remembering the value of o_name() .

    Summary

    • When we define a function inside a function that is known as a nested function.
    • Like a local variable, a nested function can only be accessed inside the function only that defines it.
    • But if we return the function it can also be accessed outside the outer function.
    • The closure property helps the nested function to keep remembering the variables and values of its function block even the outer function is done executing.